use std::{mem::MaybeUninit, ptr::NonNull};

use android_logger::Config;
use jni::{sys::jlong, JavaVM};
use log::{debug, LevelFilter};
use tokio::runtime::{Builder, Runtime};

pub mod config;
pub mod java;

static mut RT: MaybeUninit<Runtime> = MaybeUninit::uninit();
static mut JAVA_VM: MaybeUninit<JavaVM> = MaybeUninit::uninit();

pub fn new_buf(len: usize) -> Box<[u8]> {
    let mut vec = Vec::with_capacity(len);
    unsafe {
        vec.set_len(len);
    }
    vec.into_boxed_slice()
}

pub fn get_mut<T>(value: &T) -> &mut T {
    unsafe {
        NonNull::new_unchecked(value as *const T as *mut T).as_mut()
    }
}

pub fn java_init(vm: JavaVM) {

    unsafe {
        JAVA_VM.write(vm);

        let rt = Builder::new_current_thread()
        .enable_all()
        .build()
        .unwrap();
        RT.write(rt);
    }
    let cfg = Config::default()
        .with_max_level(LevelFilter::Debug)
        .with_tag("native log");
    android_logger::init_once(cfg);

    debug!("native init finish");
}

pub fn get_rt() -> &'static Runtime {
    unsafe { RT.assume_init_ref() }
}

pub fn get_vm() -> &'static JavaVM {
    unsafe { JAVA_VM.assume_init_ref() }
}

pub fn get_raw_ref<T>(fd: jlong) -> &'static T {
    unsafe {
        let n = Box::from_raw(fd as *mut T);
        Box::leak(n)
    }
}

pub fn drop_box<T>(fd: jlong) {
    unsafe {
        let n = Box::from_raw(fd as *mut T);
        drop(n);
    }
}

